package coder

import (
	"github.com/lishimeng/app-starter/tool"
	"github.com/lishimeng/go-log"
)

func (c *clientImpl) Handle(packet []byte) {
	log.Debug("<<%s", tool.BytesToHex(packet))

	cmd := packet[1]
	switch cmd {
	case CmdBusResp: // 总线帧回复
		//c.onChannelStateResp(packet)
		c.onBusResp(packet)
	case CmdRespNested: // 嵌套帧回复
		c.onNestedResp(packet)
	default:
		// unknown resp
		// TODO
	}
}

func (c *clientImpl) onBusResp(p []byte) {
	packetLen := p[2]
	c.cmdCtx.p <- string(p[3 : 3+packetLen])
}

func (c *clientImpl) onNestedResp(p []byte) {
	// TODO check
	packetLen := p[2]
	c.cmdCtx.p <- string(p[3 : 3+packetLen])
}

func (c *clientImpl) getPacketBody(p []byte) []byte {
	dataLen := p[2]
	var body = p[3 : 3+dataLen]
	return body
}

// ChannelState 测量指定通道的电压电流状态
func (c *clientImpl) ChannelState(ch *Channel) (ci ChannelInfo, err error) {
	log.Debug("channel state req")
	sc := ch.build() // selectedChannels
	go func() {
		packet := BuildPacket(CmdBusReq, append([]byte{0x0a}, sc...))
		_, _ = c.tx(packet)
	}()
	err = c.WaitResp(func(body []byte) error {
		// TODO 长度检查
		// 0x0a 电压高位 电压低位 电流高位 电流低位
		ci.Voltage = ReadUint16(body[1 : 1+2])
		ci.Electricity = ReadUint16(body[3 : 3+2])
		if ci.Voltage < c.shortCircuitThreshold {
			return ErrShortCircuit
		}
		return nil
	})

	return
}

func (c *clientImpl) GetInfo() (uid []byte, password []byte, err error) {

	go func() {
		body := BuildNestedPacket(NestCmdUIDReq, []byte{0x00, 0x0b, 0x5a, 0x6b, 0x7c, 0x8d})
		packet := BuildPacket(CmdReqNested, body)
		_, _ = c.tx(packet)
	}()
	err = c.WaitResp(func(body []byte) error {

		if len(body) == 0 {
			return ErrBrokenCircuit
		}
		// TODO 长度检测
		uid = body[6 : 6+7]
		password = body[13 : 13+4]
		return nil
	})

	return
}

// OpenAll 打开所有通道, voltage:电压值
func (c *clientImpl) OpenAll() (ci ChannelInfo, err error) {

	log.Debug("Open channel 1...10.")
	ch := &Channel{}
	for i := 1; i <= 10; i++ {
		ch.Enable(i)
	}
	ci, err = c.ChannelState(ch)

	if err != nil {
		panic(err)
	}
	return
}

// CloseAll 关闭所有通道
func (c *clientImpl) CloseAll() (err error) {
	log.Debug("Close all channels")

	go func() {
		packet := BuildPacket(CmdBusReq, []byte{0x0a, 0x00, 0x00, 0x00, 0x00})
		_, _ = c.tx(packet)
	}()
	err = c.WaitResp(func(_ []byte) error {
		return nil
	})
	return
}
